/* ----------------------------------------------------------------------------
ex1.C

DESCRIPTION: GA with 11 gene

---------------------------------------------------------------------------- */
//#include <cstdio>
//#include <cstdlib>
#pragma once

#include <algorithm>
#include <cmath>
#include <ga/GASStateGA.h>
#include <ga/GASimpleGA.h>
#include <ga/GAList.h>
#include <ga/GA1DArrayGenome.h>
#include <ga/std_stream.h>

#include <windows.h>
#include "OptInf.h"
#include "galibFuncs.h"


#define cout STD_COUT
#define cerr STD_CERR
#define endl STD_ENDL
#define ifstream STD_IFSTREAM

// force instantiations for compilers that do not do auto instantiation
// for some compilers (e.g. metrowerks) this must come after any
// specializations or you will get 'multiply-defined errors when you compile.
#if !defined(GALIB_USE_AUTO_INST)
#include <ga/GAList.C>
#include <ga/GA1DArrayGenome.C>
GALIB_INSTANTIATION_PREFIX GAList<int>;
GALIB_INSTANTIATION_PREFIX GA1DArrayGenome<float>;
#endif


namespace OptRun{

#ifndef _ENUM_GASCHEMA_
#define _ENUM_GASCHEMA_
	enum GASchema {
      OneGA,
      GAinGA,
	  GA_BFA
   };
#endif

	class OptInf;

	typedef struct _UserData{
		GA1DArrayGenome<int> *geo_genome;
		GA1DArrayGenome<int> *pro_genome;
	} UserData;

	typedef struct _MomentOrg{
		double Mb[4];
		double M1[4];
		double M2[4];
		double A[4];
		double C[4];
		double Vbr[4];
		double Vbl[4]; // for the load case 
	} MomentOrg;

	typedef struct _MomentOrg_B{
		double M1[8];
		double M2[8];
		double M3[8];
		double Mb[8];
		double Mc[8];
		double Md[8];
		double Me[8];
		double A[8];
		double B[8];
		double C[8];
		double Vbr[8];
		double Vbl[8]; // for the load case 
		double Vcr[8];
		double Vcl[8];
	} MomentOrg_B;

	typedef struct _MomentMdf_B{
		double delta_Mb[8];
		double delta_A[8];
		//double delta_C[4];
		double x0[8];
		//double y0[4];
		double B[8];
		double Vzblinks[8]; 
		double Vzbrechts[8];  
		double My1max[8]; 
		//double My2max[4]; // for the load case 
	} MomentMdf_B;

	typedef struct _MomentMdf{
		double delta_Mb[4];
		double delta_A[4];
		double delta_C[4];
		double x0[4];
		double y0[4];
		double B[4];
		double Vzblinks[4]; 
		double Vzbrechts[4];  
		double My1max[4]; 
		double My2max[4]; // for the load case 
	} MomentMdf;

	void clearMoment(MomentMdf & md, MomentOrg & mo);
	void clearMoment_B(MomentMdf_B & md, MomentOrg_B & mo);
	
	float UpdateInfoObjective(OptInf& info, GAGenome& g, GASchema gaS = GASchema::OneGA);
	void CallOptInformation(OptInf& info, GAGenome& g,GASchema gaS = GASchema::OneGA);

	//float UpdateInfoObjective(OptInf& info, GAGenome& g, GASchema gaS = GASchema::GA_BFA);
	//void CallOptInformation(OptInf& info, GAGenome& g,GASchema gaS = GASchema::GA_BFA);
	//float UpdateInfoObjective(OptInf& info, GAGenome& g, GASchema gaS = GASchema::GAinGA);
	//void CallOptInformation(OptInf& info, GAGenome& g,GASchema gaS = GASchema::GAinGA);

	//typedef struct _UserData{
	//	double fit;
	//	double temfit;
	//	double penalty;
	//	GA1DArrayGenome<int> *genome;
	//} UserData;




	int round(double);
	double BendingResistency2ndBeam(double, double, double,double ,double ,double,double,double,double,double);
	double PosBendingResistencyPriBeam(double, double, double,double,double ,double ,double,double,double ,double);
	double Deflection(double ,double ,double, double, double, double,double,double );
	double EigenFrequencySecBeam(double,double,double, double,double,double, double,double,double);
	double EigenFrequencyPriBeam(double b_eff,double h_p,double L,double b,double tf,double h, double ts ,double A,double slabt) ;
	double NegBendingResistencyPriBeam(double , double , double ,  double , double , double, double , double ,  double , double , double );


	double ShearForcePriBeam( MomentMdf & md );
	double ShearForcePriBeam_B( MomentMdf_B & md );
	double NegBendingMomentPriBeam( MomentOrg & mo );
	double NegBendingMomentPriBeam_B( MomentOrg_B & mo );
	double PosBendingMomentPriBeam( MomentMdf & md );
	double PosBendingMomentPriBeam_B( MomentMdf_B & md );
	double LoadOnSideColumn( MomentOrg & mo );
  double LoadOnMidColumn( MomentMdf & md );
  double LoadOnSideColumn_B( MomentOrg_B & mo, double ratio );
  double LoadOnSideColumnEdge_B( MomentOrg_B & mo, double ratio );
  double LoadOnMidColumn_B( MomentOrg_B & mo );
  double LoadOnMidColumnEdge_B( MomentOrg_B & mo );

  void Column_N_b_y_Rd_and_N_b_y_Rd(
    double arg_h_col,
    double arg_b_col,
    double arg_iy_col,
    double arg_iz_col,
    double arg_A_col,
    int arg_steelGrade,
    double epsilon_col,
    double arg_gamma_M1s,
    double arg_H_COL,
    double *N_b_y_Rd,
    double *N_b_z_Rd);
  
  void Column_N_b_y_Rd_and_N_b_y_Rd_and_M_b_y_Rd(
    double arg_h_col,
    double arg_b_col,
    double arg_iy_col,
    double arg_iz_col,
    double arg_A_col,
    double arg_Wply_col,
    double arg_Wplz_col,
    double arg_Iz_col,
    double arg_IT_col,
    double arg_Iw_col,
    int arg_steelGrade,
    double epsilon_col,
    double arg_gamma_M1s,
    double arg_H_COL,
    double Cmy,
    double CmLT,
    double arg_loading,
    double *N_b_y_Rd,
    double *N_b_z_Rd,
    double *M_b_y_Rd,
    double *k_yy,
    double *k_zy);

	double CatogorizeAlphaY(double,double,double);
	double CatogorizeAlphaZ(double,double,double);
	double CatogorizeAlphaLT(double,double);

	double CalLength2ndBeam(GAGenome& , double);
	double CalDist2ndBeam(double,double);
	double Calh_p(GAGenome&);
	double Calv_c(GAGenome&);
	double Calm_R(GAGenome&);
	double Calm_p(GAGenome&);
	double Calm_q(GAGenome&);
	double CalA_a(GAGenome&);
	double CalM_plRd_sec(GAGenome&);
	double CalM_yEd_sec(GAGenome&);
	double CalV_Ed_sec(GAGenome&);
	double CalV_plRd_sec(GAGenome&);
	double CalDeflection_sec(GAGenome&);
	double CalEigenFre_sec(GAGenome&);

	double CalM_plRd_neg_pri( 
		MomentMdf & md,
		MomentOrg & mo,
		GAGenome& g,
		double L2,
		double DistancePriBeam,
		double h_p
		);
	double CalM_yEd_neg_pri(
		MomentOrg & mo,
		int isTypeB
		);
	double CalM_plRd_pos_pri(
		MomentMdf & md,
		MomentOrg & mo,
		GAGenome& g,
		double L2,
		double DistancePriBeam,
		double h_p
		);
	double CalM_yEd_pos_pri(
		MomentMdf & md,
		int isTypeB
		);



	void CalMoment_pri(
		MomentMdf & md,
		MomentOrg & mo,
		double q_d,
		double g_d,
		double L2, 
		double L1,
		double C1,
		double ts,
		double C2,
		double tf,
		double f_yk
		);

	void CalMoment_pri_B(
		MomentMdf_B & md,
		MomentOrg_B & mo,
		double q_d,
		double g_d,
		double L,
		double C1,
		double ts,
		double C2,
		double tf,
		double f_yk
		);

	void CalMom_pri(
		double & M_plRd_neg_pri,
		double & M_yEd_neg_pri, 
		double & M_plRd_pos_pri, 
		double & M_yEd_pos_pri, 
		GAGenome& g);
	
	double BearingCapacityCol(
		double chi,
		double A,
		double fyk,
		double gamma);

	double TorsionalBucklingMoment(
		double Iz, 
		double Iw,
		double IT);

}